import * as THREE from 'three';

import Stats from 'three/addons/libs/stats.module.js';
import { GPUStatsPanel } from 'three/addons/utils/GPUStatsPanel.js';

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { Line2 } from 'three/addons/lines/Line2.js';
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
import { LineGeometry } from 'three/addons/lines/LineGeometry.js';
import * as GeometryUtils from 'three/addons/utils/GeometryUtils.js';

let line, renderer, scene, camera, camera2, controls;
let line1;
let matLine, matLineDashed;
let stats, gpuPanel;
let gui;
let linewidth = 4;

export function init(canvas: any, $: any) {

    renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setClearColor(0x000000, 0.0);
    renderer.setSize(window.innerWidth, window.innerHeight);
    // document.body.appendChild( renderer.domElement );

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(-40, 0, 60);
    camera.lookAt(new THREE.Vector3())

    controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.minDistance = 10;
    controls.maxDistance = 500;

    let light = new THREE.DirectionalLight(0xffffff, 0.8);
    light.position.set(200, 200, 100);
    scene.add(light)

    matLine = new LineMaterial({
        color: 0xff0000,
        linewidth, // in world units with size attenuation, pixels otherwise
        vertexColors: false,
        //resolution:  // to be set by renderer, eventually
        dashed: true,
        alphaToCoverage: true,
    });

    addLines(new THREE.Vector3(10, -100, -40), new THREE.Vector3(20, 90, 120), true);

    window.addEventListener('resize', onWindowResize);
    onWindowResize();

    animate();
}

function addLines(p1: THREE.Vector3, p2: THREE.Vector3, two = false) {
    if (two) {
        let ofs = linewidth / 2;
        p1.add(new THREE.Vector3(ofs, -ofs, 0))
        p2.add(new THREE.Vector3(ofs, -ofs, 0))
        addLine(p1, p2);
        let p3 = p1.clone().add(new THREE.Vector3(linewidth, -linewidth, 0));
        let p4 = p2.clone().add(new THREE.Vector3(linewidth, -linewidth, 0));
        addLine(p4, p3);
    }
    else {
        addLine(p1, p2);
    }

    addPot(p1)
    addPot(p2)
}

function addPot(p:THREE.Vector3){
    let geo = new THREE.SphereGeometry(linewidth * 2, 8, 8);
    let mat = new THREE.MeshStandardMaterial({color: new THREE.Color(0xff0000), flatShading: true});
    let mesh = new THREE.Mesh(geo, mat);
    
    mesh.position.set(p.x, p.y, p.z);
    scene.add(mesh);
}

function addLine(p1: THREE.Vector3, p2: THREE.Vector3) {
    const positions = [];
    positions.push(p1.x, p1.y, p1.z)
    positions.push(p2.x, p2.y, p2.z)
    const geometry = new LineGeometry();
    geometry.setPositions(positions);
    line = new Line2(geometry, matLine);
    line.computeLineDistances();
    line.scale.set(1, 1, 1);
    scene.add(line);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate() {
    requestAnimationFrame(animate);
    // main scene
    renderer.setClearColor(0x000000, 0);
    // renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
    controls.update();
    // renderer will set this eventually
    matLine.resolution.set(window.innerWidth, window.innerHeight); // resolution of the viewport
    renderer.render(scene, camera);

    matLine.dashOffset += 0.1;
}